//! Schema解析器测试
//! 
//! 测试 src/db/schema.rs 中的Schema解析功能

use dataforge::db::{SchemaParser, TableSchema, FieldSchema, DataType};
use dataforge::db::schema::{FieldConstraints, DatabaseTableInfo, DatabaseColumnInfo, DatabaseIndexInfo};

use serde_json::json;

#[test]
fn test_schema_parser_creation() {
    let parser = SchemaParser::new();
    
    // 验证解析器初始化正确
    let json_schema = json!({
        "title": "Test",
        "properties": {
            "id": {"type": "integer"}
        }
    });
    
    let result = parser.infer_from_json(&json_schema);
    assert!(result.is_ok());
}

#[test]
fn test_infer_from_json_basic() {
    let parser = SchemaParser::new();
    let json_schema = json!({
        "title": "User",
        "type": "object",
        "properties": {
            "id": {
                "type": "integer"
            },
            "name": {
                "type": "string"
            },
            "email": {
                "type": "string"
            }
        }
    });

    let result = parser.infer_from_json(&json_schema);
    assert!(result.is_ok());

    let schema = result.unwrap();
    assert_eq!(schema.name, "User");
    assert_eq!(schema.fields.len(), 3);
    
    // 验证字段类型
    let id_field = schema.fields.iter().find(|f| f.name == "id").unwrap();
    match &id_field.data_type {
        DataType::Integer { .. } => {},
        _ => panic!("Expected Integer type for id field"),
    }
}

#[test]
fn test_infer_from_json_with_description() {
    let parser = SchemaParser::new();
    let json_schema = json!({
        "title": "Product",
        "description": "Product information",
        "properties": {
            "name": {
                "type": "string",
                "description": "Product name"
            },
            "price": {
                "type": "number",
                "description": "Product price"
            }
        }
    });

    let result = parser.infer_from_json(&json_schema);
    assert!(result.is_ok());

    let schema = result.unwrap();
    assert_eq!(schema.description, Some("Product information".to_string()));
    
    let name_field = schema.fields.iter().find(|f| f.name == "name").unwrap();
    assert_eq!(name_field.description, Some("Product name".to_string()));
}

#[test]
fn test_pattern_matching_id_fields() {
    let parser = SchemaParser::new();
    
    // 测试ID字段识别
    let id_type = parser.infer_data_type("user_id", &json!({})).unwrap();
    match id_type {
        DataType::Integer { .. } => {},
        _ => panic!("Expected Integer type for ID field"),
    }
    
    let another_id_type = parser.infer_data_type("product_id", &json!({})).unwrap();
    match another_id_type {
        DataType::Integer { .. } => {},
        _ => panic!("Expected Integer type for ID field"),
    }
}

#[test]
fn test_pattern_matching_email_fields() {
    let parser = SchemaParser::new();
    
    // 测试邮箱字段识别
    let email_type = parser.infer_data_type("user_email", &json!({})).unwrap();
    match email_type {
        DataType::Email => {},
        _ => panic!("Expected Email type for email field"),
    }
    
    let mail_type = parser.infer_data_type("contact_mail", &json!({})).unwrap();
    match mail_type {
        DataType::Email => {},
        _ => panic!("Expected Email type for mail field"),
    }
}

#[test]
fn test_pattern_matching_phone_fields() {
    let parser = SchemaParser::new();
    
    let phone_type = parser.infer_data_type("phone_number", &json!({})).unwrap();
    match phone_type {
        DataType::Phone { country } => {
            assert_eq!(country, Some("CN".to_string()));
        },
        _ => panic!("Expected Phone type for phone field"),
    }
}

#[test]
fn test_pattern_matching_datetime_fields() {
    let parser = SchemaParser::new();
    
    let created_type = parser.infer_data_type("created_at", &json!({})).unwrap();
    match created_type {
        DataType::DateTime { .. } => {},
        _ => panic!("Expected DateTime type for created_at field"),
    }
    
    let updated_type = parser.infer_data_type("updated_at", &json!({})).unwrap();
    match updated_type {
        DataType::DateTime { .. } => {},
        _ => panic!("Expected DateTime type for updated_at field"),
    }
}

#[test]
fn test_database_type_mapping() {
    let parser = SchemaParser::new();
    
    // 测试基本类型映射
    let varchar_type = parser.map_database_type("VARCHAR(255)").unwrap();
    match varchar_type {
        DataType::String { max_length: Some(255) } => {},
        _ => panic!("Expected String type with max_length for VARCHAR"),
    }

    let int_type = parser.map_database_type("INTEGER").unwrap();
    match int_type {
        DataType::Integer { .. } => {},
        _ => panic!("Expected Integer type for INTEGER"),
    }
    
    let bool_type = parser.map_database_type("BOOLEAN").unwrap();
    match bool_type {
        DataType::Boolean => {},
        _ => panic!("Expected Boolean type for BOOLEAN"),
    }
}

#[test]
fn test_custom_type_mapping() {
    let mut parser = SchemaParser::new();
    
    // 添加自定义类型映射
    parser.add_type_mapping(
        "custom_type".to_string(),
        DataType::Custom {
            type_name: "CustomType".to_string(),
            generator: "custom_generator".to_string(),
        }
    );

    let custom_type = parser.map_database_type("custom_type").unwrap();
    match custom_type {
        DataType::Custom { type_name, generator } => {
            assert_eq!(type_name, "CustomType");
            assert_eq!(generator, "custom_generator");
        },
        _ => panic!("Expected Custom type"),
    }
}

#[test]
fn test_pattern_rule_priority() {
    let mut parser = SchemaParser::new();
    
    // 添加高优先级规则
    parser.add_pattern_rule(r"(?i)^special_.*$", DataType::Uuid, 200).unwrap();
    
    let special_type = parser.infer_data_type("special_id", &json!({})).unwrap();
    match special_type {
        DataType::Uuid => {},
        _ => panic!("Expected Uuid type for special field with high priority rule"),
    }
}

#[test]
fn test_infer_from_database_table() {
    let parser = SchemaParser::new();
    
    let table_info = DatabaseTableInfo {
        name: "users".to_string(),
        columns: vec![
            DatabaseColumnInfo {
                name: "id".to_string(),
                data_type: "INTEGER".to_string(),
                nullable: false,
                unique: true,
                default_value: None,
                comment: Some("User ID".to_string()),
            },
            DatabaseColumnInfo {
                name: "name".to_string(),
                data_type: "VARCHAR(100)".to_string(),
                nullable: false,
                unique: false,
                default_value: None,
                comment: None,
            },
            DatabaseColumnInfo {
                name: "email".to_string(),
                data_type: "VARCHAR(255)".to_string(),
                nullable: true,
                unique: true,
                default_value: None,
                comment: None,
            },
        ],
        primary_key: vec!["id".to_string()],
        indexes: vec![
            DatabaseIndexInfo {
                name: "idx_email".to_string(),
                columns: vec!["email".to_string()],
                unique: true,
            }
        ],
        comment: Some("User table".to_string()),
    };
    
    let result = parser.infer_from_database_table(&table_info);
    assert!(result.is_ok());
    
    let schema = result.unwrap();
    assert_eq!(schema.name, "users");
    assert_eq!(schema.fields.len(), 3);
    assert_eq!(schema.primary_key, Some(vec!["id".to_string()]));
    assert_eq!(schema.indexes.len(), 1);
    assert_eq!(schema.description, Some("User table".to_string()));
    
    // 验证字段约束
    let email_field = schema.fields.iter().find(|f| f.name == "email").unwrap();
    assert!(email_field.constraints.nullable);
    assert!(email_field.constraints.unique);
}

#[test]
fn test_field_constraints() {
    let constraints = FieldConstraints {
        nullable: true,
        unique: false,
        default: Some(json!("default_value")),
        pattern: Some(r"^\d+$".to_string()),
        min: Some(json!(0)),
        max: Some(json!(100)),
    };
    
    assert!(constraints.nullable);
    assert!(!constraints.unique);
    assert_eq!(constraints.default, Some(json!("default_value")));
    assert_eq!(constraints.pattern, Some(r"^\d+$".to_string()));
}

#[test]
fn test_data_type_variants() {
    let string_type = DataType::String { max_length: Some(255) };
    let integer_type = DataType::Integer { min: Some(0), max: Some(100) };
    let float_type = DataType::Float { min: Some(0.0), max: Some(1.0), precision: Some(2) };
    let boolean_type = DataType::Boolean;
    let datetime_type = DataType::DateTime { format: Some("ISO8601".to_string()) };
    let uuid_type = DataType::Uuid;
    let email_type = DataType::Email;
    
    // 验证类型创建成功
    match string_type {
        DataType::String { max_length: Some(255) } => {},
        _ => panic!("String type mismatch"),
    }
    
    match integer_type {
        DataType::Integer { min: Some(0), max: Some(100) } => {},
        _ => panic!("Integer type mismatch"),
    }
    
    match boolean_type {
        DataType::Boolean => {},
        _ => panic!("Boolean type mismatch"),
    }
}

#[test]
fn test_invalid_regex_pattern() {
    let mut parser = SchemaParser::new();
    
    // 测试无效的正则表达式
    let result = parser.add_pattern_rule(r"[invalid", DataType::String { max_length: None }, 50);
    assert!(result.is_err());
}

#[test]
fn test_unsupported_database_type() {
    let parser = SchemaParser::new();
    
    // 测试不支持的数据库类型
    let result = parser.map_database_type("UNSUPPORTED_TYPE");
    assert!(result.is_err());
}